package com.whl215.kit.grape.ui

import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.GridLayoutManager
import com.whl215.kit.adapter.GrapeBaseAdapter
import com.whl215.kit.adapter.GrapeNodeAdapter
import com.whl215.kit.adapter.element.GrapeAction
import com.whl215.kit.adapter.element.LoadMoreGrapeElement
import com.whl215.kit.adapter.wrap.GrapeNodeWrapper
import com.whl215.kit.grape.R
import com.whl215.kit.grape.databinding.ActivityShopCartBinding
import com.whl215.kit.grape.model.GoodsBean
import com.whl215.kit.grape.model.ShopBean
import com.whl215.kit.grape.tools.ToastTool
import com.whl215.kit.grape.wrapper.GoodsOfOneInRowNodeWrapper
import com.whl215.kit.grape.wrapper.GoodsOfTwoInRowNodeWrapper
import com.whl215.kit.grape.wrapper.ShopCartNodeWrapper
import com.whl215.kit.grape.wrapper.ShopNodeWrapper

/**
 * author： happiness
 * date： 2021/5/5
 * description：购物车案例  介绍分组 和多类型列表的使用
 *
 * 案例完成之后 发现在 选中,商品,店铺时
 * 为了获取数据会产生多次强转GrapeNodeWrapper->Shop/GoodsWrapper-->getItem as ShopBean/GoodsBean
 * 购物车是分组和多类型结合案例 GrapeNodeAdapter 继承 GrapeBaseMultiAdapter 数据类型 固定 GrapeNodeWrapper
 * GrapeNodeAdapter 不可修改泛型
 * GrapeNodeWrapper 可以理解为 分组功能的实现 不掺杂业务 而 Shop/GoodsWrapper 属于业务范畴
 * 为了减少类型转换的次数 决定允许 GrapeNodeAdapter 修改泛型
 * 结合购物车案例.
 * 1.创建 ShopCartItemWrapper. 继承 GrapeNodeWrapper. 包含业务字段 isSelected 业务方法 getPrice
 * 2.创建 ShopCartNodeAdapter. 继承 GrapeNodeAdapter 泛型 ShopCartItemWrapper
 * 3.Shop/GoodsWrapper 实现 ShopCartItemWrapper
 * --------------------------------------
 * 由于实现机制的问题..ShopCartNodeAdapter失败了 不太行
 * 1,3还是可以实施的 为wrapper做一层业务封装 减少一次强转也不错
 */
class ShopCartActivity : AppCompatActivity(), View.OnClickListener {
    private lateinit var mViewBinding: ActivityShopCartBinding
    private lateinit var mAdapter: GrapeNodeAdapter
    private var pageIndex = 0
    private var totalPage = 4

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mViewBinding = ActivityShopCartBinding.inflate(layoutInflater)
        setContentView(mViewBinding.root)
        mAdapter = GrapeNodeAdapter()
        val gridLayoutManager = GridLayoutManager(this, 2)
        gridLayoutManager.spanSizeLookup = spanSizeLookup
        mViewBinding.rvContent.layoutManager = gridLayoutManager
        mViewBinding.rvContent.adapter = mAdapter

        setUpAdapter()
        mAdapter.setData(fetchData(5))
        calculateFooterInfo()
        mViewBinding.cbMemberSelectedAll.setOnClickListener(this)
        mViewBinding.btnFooterAddOne.setOnClickListener(this)
    }

    private fun setUpAdapter() {
        mAdapter.onItemClickListener = object : GrapeBaseAdapter.OnItemClickListener {
            override fun onItemClick(adapter: GrapeBaseAdapter<*>, view: View, position: Int) {
                val wrapper = mAdapter.getItem(position)
                when {
                    wrapper.getViewType() == R.layout.item_wrapper_node_goods_of_one_in_row -> {
                        val item = wrapper.getItem() as GoodsBean
                        ToastTool.showToast(view.context, item.name)
                    }
                    wrapper.getViewType() == R.layout.item_wrapper_node_goods_of_two_in_row -> {
                        val item = wrapper.getItem() as GoodsBean
                        ToastTool.showToast(view.context, item.name)
                    }
                }
            }
        }
        mAdapter.onChildClickListener = object : GrapeBaseAdapter.OnChildClickListener {
            override fun onChildClick(adapter: GrapeBaseAdapter<*>, view: View, position: Int) {
                val wrapper = mAdapter.getItem(position)
                when (view.id) {
                    R.id.item_cb_shop_selected -> {
                        selectedShop(position,wrapper)
                    }
                    R.id.item_cb_goods_selected -> {
                        selectedGoods(wrapper)
                    }
                    R.id.item_btn_expend_collapse -> {
                        if (wrapper.isExpend) mAdapter.collapse(position)
                        else mAdapter.expend(position)
                        mAdapter.notifyItemChanged(position)
                    }
                    R.id.item_btn_add -> {
                        val shopWrapper: ShopNodeWrapper = wrapper as ShopNodeWrapper
                        val strId = (1..100000).random().toString()
                        val goods = GoodsBean(strId, "商品${strId}", (1..100).random())
                        if (shopWrapper.shopType == ShopNodeWrapper.ONE_IN_ROW) {
                            mAdapter.addNode(position, GoodsOfOneInRowNodeWrapper(goods))
                        } else if (shopWrapper.shopType == ShopNodeWrapper.TWO_IN_ROW) {
                            mAdapter.addNode(position, GoodsOfTwoInRowNodeWrapper(goods))
                        }
                    }
                    R.id.item_tv_delete -> {
                        mAdapter.removeAt(position)
                    }
                }
            }
        }
        mAdapter.loadMoreElement.onLoadMoreListener =
            object : LoadMoreGrapeElement.OnLoadMoreListener {
                override fun onLoadMore() {
                    if (pageIndex >= totalPage) {
                        mAdapter.loadMoreAction = GrapeAction.buildLoadMoreCompletionAction()
                    } else {
                        mViewBinding.rvContent.postDelayed({
                            mAdapter.addNode(list = fetchData(10))
                            mAdapter.loadMoreAction = GrapeAction.buildLoadMoreEndAction()
                        }, 2000)
                    }
                }
            }
    }


    /**
     * 模拟数据
     */
    private fun fetchData(count: Int): List<GrapeNodeWrapper> {
        val list = mutableListOf<GrapeNodeWrapper>()
        for (i in 1..count) {
            val shopBean = ShopBean("${pageIndex}${i}", "商店${pageIndex}${i}", mutableListOf())
            for (j in 1..6) {
                val strId = "${pageIndex}${i}${j}"
                val goods = GoodsBean(strId, "商品${strId}", (1..100).random())
                shopBean.children.add(goods)
            }
            val shopWrapper = ShopNodeWrapper(
                shopBean,
                if (i % 2 == 0) ShopNodeWrapper.ONE_IN_ROW else ShopNodeWrapper.TWO_IN_ROW
            )
            shopWrapper.isExpend = i != 2 //设置分组的展开 收起
            list.add(shopWrapper)
        }
        pageIndex++
        return list
    }


    /**
     * 本来想着 复用方法 selectedAllMember() 调用 selectedShop()
     */
    private fun selectedAllMember() {
        var totalMember = 0
        var totalMoney = 0
        for (wrapper in mAdapter.getList()) {
            when {
                wrapper.getViewType() == R.layout.item_wrapper_node_shop -> {
                    val child = wrapper as ShopCartNodeWrapper
                    child.isSelected = mViewBinding.cbMemberSelectedAll.isChecked
                }
                wrapper.getViewType() == R.layout.item_wrapper_node_goods_of_one_in_row -> {
                    val child = wrapper as ShopCartNodeWrapper
                    child.isSelected = mViewBinding.cbMemberSelectedAll.isChecked
                    if (child.isSelected) {
                        totalMember = totalMember.plus(1)
                        totalMoney = totalMoney.plus(child.getPrice())
                    }
                }
                wrapper.getViewType() == R.layout.item_wrapper_node_goods_of_two_in_row -> {
                    val child = wrapper as ShopCartNodeWrapper
                    child.isSelected = mViewBinding.cbMemberSelectedAll.isChecked
                    if (child.isSelected) {
                        totalMember = totalMember.plus(1)
                        totalMoney = totalMoney.plus(child.getPrice())
                    }
                }
            }
        }
        setUpFooterInfo(totalMember, totalMoney)
    }

    /**
     * 选中店铺
     */
    private fun selectedShop(position:Int,wrapper: GrapeNodeWrapper) {
        val shopWrapper:ShopNodeWrapper = wrapper as ShopNodeWrapper
        shopWrapper.isSelected = !shopWrapper.isSelected
        for (item in wrapper.getChildren()) {
            when {
                item.getViewType() == R.layout.item_wrapper_node_goods_of_one_in_row -> {
                    val child = item as GoodsOfOneInRowNodeWrapper
                    child.isSelected = shopWrapper.isSelected
                }
                item.getViewType() == R.layout.item_wrapper_node_goods_of_two_in_row -> {
                    val child = item as GoodsOfTwoInRowNodeWrapper
                    child.isSelected = shopWrapper.isSelected
                }
            }
        }
        if (shopWrapper.isExpend&&wrapper.getChildren().isNotEmpty()){
            mAdapter.notifyItemRangeChanged(position+1,wrapper.getChildren().size)
        }
        calculateFooterInfo()
    }

    /**
     * 选中商品
     * 1.当前状态反选
     * 2.根据parentId 找到对应店铺 遍历店铺下商品  查看商品是否全部选中  设置当前商店状态
     *      2.1当前商品选中 其他商品未全部选中 则商店未选中
     *      2.2当前商品选中 其他商品全部选中 则商店选中
     *          同时遍历所有店铺是否选中 如果其他店铺全部选中 则设置底部全选框选中
     *      2.3当前商品取消选中 商店未选中状态 不需要处理
     *      2.4当前商品取消选中 商店选中状态 修改商店状态为未选中
     *          查看底部全选框状态 如果选中状态 修改为取消状态
     *  3.重新计算底部展示的汇总价格
     */
    private fun selectedGoods(currWrapper: GrapeNodeWrapper) {
        //获取商品对应的商店id
        var groupId = ""
        when {
            currWrapper.getViewType() == R.layout.item_wrapper_node_goods_of_one_in_row -> {
                val child = currWrapper as GoodsOfOneInRowNodeWrapper
                child.isSelected = !child.isSelected
                groupId = child.groupId
            }
            currWrapper.getViewType() == R.layout.item_wrapper_node_goods_of_two_in_row -> {
                val child = currWrapper as GoodsOfTwoInRowNodeWrapper
                child.isSelected = !child.isSelected
                groupId = child.groupId
            }
        }
        //找到商品所属的商店
        val pair = findShopById(groupId)
        if (pair != null) {
            val position = pair.first
            val shopWrapper = pair.second
            val newStatus = queryAllGoodsAreSelectedInShop(shopWrapper)
            //新旧状态不一致 才更新数据,UI
            if (newStatus != shopWrapper.isSelected) {
                shopWrapper.isSelected = newStatus
                mAdapter.notifyItemChanged(position)
                if (shopWrapper.isSelected) {
                    //商店选中状态才去检查 所有商店是否全部选中
                    mViewBinding.cbMemberSelectedAll.isChecked = queryAllShopAreSelected()
                }else{
                    mViewBinding.cbMemberSelectedAll.isChecked =false
                }
            }

//            else {
//                //商店没有选中 不涉及全选逻辑
//            }
        }
        calculateFooterInfo()
    }

    /**
     * 根据id查找商店
     * 返回两个值
     *      1.商店在列表中的位置
     *      2.商店数据实体
     */
    private fun findShopById(groupId: String): Pair<Int, ShopNodeWrapper>? {
        for (i in mAdapter.getList().indices) {
            val wrapper = mAdapter.getItem(i)
            if (wrapper.getItemId() == groupId &&
                wrapper.getViewType() == R.layout.item_wrapper_node_shop
            ) {
                return Pair(i, wrapper as ShopNodeWrapper)
            }
        }
        return null
    }

    /**
     * 查询当前商店下的商品是否全部选中
     */
    private fun queryAllGoodsAreSelectedInShop(shopWrapper: ShopNodeWrapper): Boolean {
        var isPass = true
        for (childWrapper in shopWrapper.getChildren()) {
            when {
                childWrapper.getViewType() == R.layout.item_wrapper_node_goods_of_one_in_row -> {
                    val child = childWrapper as GoodsOfOneInRowNodeWrapper
                    if (!child.isSelected) {
                        isPass = false
                        break
                    }

                }
                childWrapper.getViewType() == R.layout.item_wrapper_node_goods_of_two_in_row -> {
                    val child = childWrapper as GoodsOfTwoInRowNodeWrapper
                    if (!child.isSelected) {
                        isPass = false
                        break
                    }
                }
            }
        }
        return isPass
    }

    /**
     * 查询所有商品是否全部选中
     */
    private fun queryAllShopAreSelected(): Boolean {
        for (wrapper in mAdapter.getList()) {
            if (wrapper.getViewType() == R.layout.item_wrapper_node_shop) {
                val item = wrapper as ShopNodeWrapper
                if (!item.isSelected) {
                    return false
                }
            }
        }
        return true
    }

    /**
     * 计算钱 还是必须要单独写一个 遍历方法的
     */
    private fun calculateFooterInfo() {
        var totalMember = 0
        var totalMoney = 0
        for (wrapper in mAdapter.getList()) {
            if (wrapper.getViewType() == R.layout.item_wrapper_node_goods_of_one_in_row) {
                val goodsWrapper: GoodsOfOneInRowNodeWrapper = wrapper as GoodsOfOneInRowNodeWrapper
                if (goodsWrapper.isSelected) {
                    val item: GoodsBean = wrapper.getItem() as GoodsBean
                    totalMember = totalMember.plus(1)
                    totalMoney = totalMoney.plus(item.price)
                }

            } else if (wrapper.getViewType() == R.layout.item_wrapper_node_goods_of_two_in_row) {
                val goodsWrapper: GoodsOfTwoInRowNodeWrapper = wrapper as GoodsOfTwoInRowNodeWrapper
                if (goodsWrapper.isSelected) {
                    val item: GoodsBean = wrapper.getItem() as GoodsBean
                    totalMember = totalMember.plus(1)
                    totalMoney = totalMoney.plus(item.price)
                }
            }
        }
        setUpFooterInfo(totalMember, totalMoney)
    }

    /**
     * 设置底部 价格 数量信息
     */
    private fun setUpFooterInfo(totalMember: Int, totalMoney: Int) {
        mViewBinding.tvFooterInfo.text = String.format("选中${totalMember}个商品 共￥${totalMoney}")
    }

    /**
     * 设置 recyclerView 每行展示数量
     */
    private val spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
        override fun getSpanSize(position: Int): Int {
            return if (mAdapter.loadMoreElement.ableLoadMore) {
                if (position == mAdapter.getList().size) {
                    2
                } else {
                    mAdapter.getItem(position).getSpanSize()
                }
            } else {
                mAdapter.getItem(position).getSpanSize()
            }
        }
    }

    /**
     * 点击事件
     */
    override fun onClick(v: View?) {
        if (v == mViewBinding.cbMemberSelectedAll) {
            selectedAllMember()
            mAdapter.notifyDataSetChanged()
        } else if (v == mViewBinding.btnFooterAddOne) {
            pageIndex++
            mAdapter.addNode(item = fetchData(2)[1])
        }
    }
}